#pragma once
#include <functional>
#include "Connection.hpp"

using func_t = std::function<std::string(std::string &)>;
class IOServer : public Connection
{
    const int size = 1024;

public:
    IOServer(int sockfd)
    {
        // 设置参数，EPOLLOUT非 常开事件
        Setfd(sockfd);
        // 设置为非阻塞
        SetNonBlock(sockfd);
        SetEvent(EPOLLIN | EPOLLET);
    }
    void Recver() override
    {
        // ET模式循环读取
        while (true)
        {
            char buffer[size];
            int n = recv(Fd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                AppendInbuffer(buffer);
            }
            else if (n == 0)
            {
                // 对端关闭
                Excepter();
                return;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    // 发生错误
                    Excepter();
                    return;
                }
            }
        }
        // 读到报文
        LOG(LogLevel::DEBUG) << "message :" << InBuffer();
        // 处理信息，完成业务
        std::string result;
        if (_message_handler)
            result = _message_handler(InBuffer());

        // 建立应答
        AppendOutbuffer(result);

        if (!IsOutBufferEmpty())
        {
            // 开启写事件
            GetOwner()->EnableReadWrite(Fd(),true,true);
        }
    }
    void Sender() override
    {
        // 直接写
        while (true)
        {
            ssize_t n = send(Fd(), OutString().c_str(), OutString().size(), 0);
            if (n > 0)
            {
                // 成功
                DisCardOutString(n); // 移除N个,面向字节流
            }
            else if (n == 0)
            {
                break;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    // 缓冲区写满了，下次再来
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Excepter();
                    return;
                }
            }
        }
        // 一种：outbuffer empty
        // 一种：发送缓冲区被写满了 && outbuffer没有empty，写条件不满足，使能sockfd在epoll中的事件
        if (!IsOutBufferEmpty())
        {
            // 修改对sockfd的事件关心！-- 开启对写事件关心
            // 按需设置！
            GetOwner()->EnableReadWrite(Fd(), true, true);
        }
        else
        {
            GetOwner()->EnableReadWrite(Fd(), true, false);
        }
    }
    void Excepter() override
    {
        LOG(LogLevel::INFO) << "客户端连接可能结束，进行异常处理: " << Fd();
        GetOwner()->DelConnection(Fd());
    }
    void RegisterMessageHandler(func_t func)
    {
        _message_handler = func;
    }

private:
    func_t _message_handler;
};